package com.rabbit.api;

import cn.hutool.core.date.StopWatch;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.rabbit.constant.ConfigKey;
import com.rabbit.redis.constant.RedisKeyConstant;
import com.rabbit.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * <h1>第三方接口API</h1>
 *
 * @author zjw
 * @date 2022/01/24 21:04
 */
@Service
@Slf4j
public class RemoteApiService {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private RedisService redisService;

    /**
     * 根据IP获取真实地址API(该地址因不会变所以定义在类中，如真实三方接口需考虑不同环境）
     */
    private final String locationApi = "http://whois.pconline.com.cn/ipJson.jsp";

    /**
     * 默认地址
     */
    private final String defaultLocation = "未开启记录地址配置项";

    /**
     * 根据IP获取实际登录地址
     *
     * @param ip IP地址
     * @return String 实际地址
     */
    public String getLoginLocation(String ip) {
        String loginLocationRecord = String.valueOf(redisService.hGet(RedisKeyConstant.SYS_CONFIG, ConfigKey.LOGIN_LOCATION_RECORD));
        if (Objects.equals(loginLocationRecord, "true")) {
            return getRealAddressByIp(ip);
        } else {
            return defaultLocation;
        }
    }

    /**
     * 根据IP获取实际操作地址
     *
     * @param ip IP地址
     * @return String 实际地址
     */
    public String getOperLocation(String ip) {
        String operLocationRecord = String.valueOf(redisService.hGet(RedisKeyConstant.SYS_CONFIG, ConfigKey.OPER_LOCATION_RECORD));
        if (Objects.equals(operLocationRecord, "true")) {
            return getRealAddressByIp(ip);
        } else {
            return defaultLocation;
        }
    }

    /**
     * 根据IP获取真实物理地址
     *
     * @param ip IP地址
     * @return String 实际地址
     */
    private String getRealAddressByIp(String ip) {
        if (NetUtil.isInnerIP(ip)) {
            return "内网IP";
        } else {
            log.info("*** 开始调用【根据IP获取物理地址】接口,IP:{} ***", ip);
            try {
                StopWatch stopWatch = StopWatch.create(IdUtil.fastSimpleUUID());
                stopWatch.start();
                ResponseEntity<String> locationRes = restTemplate.getForEntity(locationApi + "?ip=" + ip + "&json=true",
                        String.class);
                stopWatch.stop();
                long costTime = stopWatch.getLastTaskTimeMillis();
                HttpStatus httpStatus = locationRes.getStatusCode();
                if (Objects.equals(httpStatus, HttpStatus.OK)) {
                    log.info("调用【根据IP获取物理地址】接口成功，耗时：{} ms ，结果:{} ", costTime, locationRes.getBody());
                    JSONObject obj = JSONObject.parseObject(locationRes.getBody());
                    String region = obj.getString("pro");
                    String city = obj.getString("city");
                    return String.format("%s %s", region, city);
                } else {
                    log.error("调用【根据IP获取物理地址】接口响应码异常 , 耗时：{} ms ,响应码:{} ", costTime, httpStatus.value());
                    return "调用地址服务异常";
                }
            } catch (Exception e) {
                log.error("调用【根据IP获取物理地址】接口失败 ,具体原因：", e);
                return "调用地址服务失败";
            }
        }
    }
}
